//
//  GlobalMethod+Auth.m
//  MexicoLoan
//
//  Created by wxp on 2025/2/26.
//

#import "GlobalMethod+Auth.h"
#import <AVFoundation/AVFoundation.h>
#import <AddressBook/AddressBook.h>
#import <ContactsUI/ContactsUI.h>
#import <EventKit/EventKit.h>

@implementation GlobalMethod (Auth)

#pragma mark - 是否已开启相机权限
+ (void)isOpenCamearPermissionsWithCompletion:(void (^)(BOOL granted))completion {
    // 获取相机的授权状态
    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (status == AVAuthorizationStatusNotDetermined) {
        // 尚未选择，发起请求
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
            if (completion) {
                completion(granted);
            }
        }];
    } else if (status == AVAuthorizationStatusRestricted || status == AVAuthorizationStatusDenied) {
        // 由于家长控制等限制 / 用户已拒绝访问相机
        AccreditRemindView * view = [AccreditRemindView new];
        [view resetViewWithContent:PERMISSIONS_CAMERA_DESC ensure:@"Determinar" cancel:@"Cancelación"];
        view.blockEnsure = ^{
            NSURL * url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
            if ([[UIApplication sharedApplication] canOpenURL:url]){
                [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
            }
        };
        view.centerY = SCREEN_HEIGHT/2;
        [[UIApplication sharedApplication].windows.firstObject addSubview:view];
        if (completion) {
            completion(false);
        }
    } else {
        // 相机权限已经被授权
        if (completion) {
            completion(true);
        }
    }
}

#pragma mark - 获取设备信息
// 设备信息
+ (void)getDeviceInfoBlock:(void (^)(NSDictionary * dic))block{
    [GlobalMethod hitPointWithPageName:KEY_ExtInfoUpload action:KEY_DeviceInfo_Fetch extInfo:nil];
    [[LocationService sharedInstance] startUpdatingLocation];
    NSString * idfa = [GlobalMethod getIDFA];
    NSString * idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    int simulator = 0;
#if TARGET_IPHONE_SIMULATOR
    simulator = 1;
#else
    simulator = 0;
#endif
    NSUInteger lastLoginTime = [GlobalMethod getDeviceLastStartUpTime]/1000;
    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
    NSString *developmentRegion = [infoDictionary objectForKey:@"CFBundleDevelopmentRegion"];
    NSString * languageCode = isStr(developmentRegion) ? developmentRegion : @"en";
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    NSDictionary *attributes = [fileManager attributesOfFileSystemForPath:NSHomeDirectory() error:&error];
    NSString * storage = @"";
    if (error) {
    } else {
        NSNumber *totalSize = [attributes objectForKey:NSFileSystemSize];
        storage = [NSString stringWithFormat:@"%lld", [totalSize longLongValue]];
    }
    CGRect screenBounds = [UIScreen mainScreen].bounds;
    CGFloat screenScale = [UIScreen mainScreen].scale;
    CGFloat screenWidth = screenBounds.size.width * screenScale;
    CGFloat screenHeight = screenBounds.size.height * screenScale;
    NSString * resolution = [NSString stringWithFormat:@"%.0fx%.0f",screenWidth,screenHeight];
    NSDictionary * batteryStatusDic = [self getDeviceBatteryInfo];
    CLLocationCoordinate2D currentLocation = [[LocationService sharedInstance] getCurrentLocation];
    NSString * lat = @"";
    if (currentLocation.latitude != 0) {
        lat = [NSString stringWithFormat:@"%f", currentLocation.latitude];
    }
    NSString * lon = @"";
    if (currentLocation.longitude != 0) {
        lon = [NSString stringWithFormat:@"%f", currentLocation.longitude];
    }
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    CLLocation *location = [[CLLocation alloc] initWithLatitude:currentLocation.latitude longitude:currentLocation.longitude];
    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> *placemarks, NSError *error) {
        NSDictionary * dic = @{
            KEY_battery_status: batteryStatusDic,
            KEY_general_data: [GlobalMethod getDeviceGeneralDataInfo],
            KEY_hardware: [self gainDeviceHardwareInfo],
            KEY_other_data: [self gainDeviceOtherInfo],
            KEY_new_storage: [self gainDeviceStorageInfo],
            KEY_process_info: [self gainDeviceProcessInfo],
            KEY_shortVersionString: readStr([GlobalMethod getBundleVersion]),
            KEY_version: readStr([GlobalMethod getVersion]),
            KEY_create_time: [GlobalMethod getTimeStampMillisecond],
            KEY_bundleId: [GlobalMethod getBundleIdentifier],
            KEY_app_name: [GlobalMethod getAppName],
            KEY_developmentRegion: readStr(languageCode),
            KEY_device_info: [GlobalMethod getDeviceModelName],
            KEY_os_type: @"ios",
            KEY_os_version: [[UIDevice currentDevice] systemVersion],
            KEY_memory: [GlobalMethod getDeviceActiveMemory],
            KEY_storage: readStr(storage),
            KEY_unuse_storage: [NSString stringWithFormat:@"%ld",[UIDevice freeDiskSpaceInBytes]],
            KEY_gps_latitude: readStr(lat),
            KEY_gps_longitude: readStr(lon),
            KEY_battery: [batteryStatusDic numberValueForKey:KEY_battery_pct],
            KEY_gps_address_province: @"",
            KEY_gps_address_city: @"",
            KEY_gps_address_street: @"",
            KEY_is_simulator: [NSNumber numberWithInt: simulator],
            KEY_last_login_time: [NSNumber numberWithInteger: lastLoginTime],
            KEY_idfv: readStr(idfv),
            KEY_idfa: readStr(idfa),
            KEY_resolution: resolution,
        };
        if (error) {
            // 未开启手机定位
            if(block){
                block(dic);
            }
            return;
        }
        CLPlacemark *placemark = [placemarks firstObject];
        if (placemark) {
            NSString *province = placemark.administrativeArea;
            NSString *city = placemark.locality;
            NSString *district = placemark.subLocality;
            NSMutableDictionary *mutableDic = [dic mutableCopy];
            [mutableDic setValue:readStr(province) forKey:KEY_gps_address_province];
            [mutableDic setValue:readStr(city) forKey:KEY_gps_address_city];
            [mutableDic setValue:readStr(district) forKey:KEY_gps_address_street];
            if(block){
                block(mutableDic);
            }
        }
    }];
}

#pragma mark - 获取 设备-电量信息
+ (NSDictionary *)getDeviceBatteryInfo{
    UIDevice * device = [UIDevice currentDevice];
    device.batteryMonitoringEnabled = true;
    float batteryLevel = [device batteryLevel]*100;
    UIDeviceBatteryState batteryState = [device batteryState];
    NSDictionary * dic = @{
        KEY_battery_pct:   @([strDotF(batteryLevel) integerValue]),
        KEY_battery_state: @(batteryState),
    };
    return  dic;
}

#pragma mark - 获取 设备-基本信息
+ (NSDictionary *)getDeviceGeneralDataInfo{
    NSString * networkType = [GlobalMethod getDeviceNetworkType];
    NSUInteger elapsedRealtime = [GlobalMethod getStartDeviceMillisecondsIncludingSleep];
    NSUInteger uptimeMillis    = [GlobalMethod getStartDeviceMillisecondsExcludingSleep];
    NSDictionary * dic = @{
        KEY_currentSystemTime: @([[GlobalMethod getTimeStamp] integerValue]*1000),
        KEY_elapsedRealtime: [NSNumber numberWithUnsignedLongLong:elapsedRealtime],
        KEY_is_using_proxy_port: @([GlobalMethod isUsingProxy]),
        KEY_is_using_vpn: @([GlobalMethod isUsingVPN]),
        KEY_serviceCurrentRadioAccessTechnology: [self currentRadioAccessTechnology],
        KEY_network_type: readStr(networkType),
        KEY_network_type_new: readStr(networkType),
        KEY_time_zone_id: readStr([[NSTimeZone localTimeZone] abbreviation]),
        KEY_uptimeMillis: [NSNumber numberWithUnsignedLongLong:uptimeMillis],
        KEY_uuid: [GlobalMethod getUserRandomKey],
    };
     return  dic;
}

#pragma mark - 获取 设备-硬件信息
+ (NSDictionary *)gainDeviceHardwareInfo{
    CGRect screenBounds = [UIScreen mainScreen].bounds;
    CGFloat screenScale = [UIScreen mainScreen].scale;
    CGFloat screenWidth = screenBounds.size.width * screenScale;
    CGFloat screenHeight = screenBounds.size.height * screenScale;
    NSDictionary * dic = @{
        KEY_device_height: @(screenHeight),
        KEY_device_name: [[UIDevice currentDevice] name],
        KEY_device_width: @(screenWidth),
        KEY_model: [GlobalMethod getDeviceModelName],
        KEY_physical_size: [GlobalMethod getScreenDiagonalSize],
        KEY_release: [[UIDevice currentDevice] systemVersion],
    };
    return dic;
}

#pragma mark - 获取设备 - 其他信息
+ (NSDictionary *)gainDeviceOtherInfo{
    int simulator = 0;
#if TARGET_IPHONE_SIMULATOR
    simulator = 1;
#else
    simulator = 0;
#endif
    NSDictionary * dic = @{
        KEY_dbmClass: [NSNumber numberWithInt:-1],
        KEY_keyboard: [NSNumber numberWithInt:1],
        KEY_last_boot_time: [NSNumber numberWithLong:[GlobalMethod getDeviceLastStartUpTime]],
        KEY_simulator: [NSNumber numberWithInt:simulator],
    };
    return dic;
}

#pragma mark - 获取设备-存储信息
+ (NSDictionary *)gainDeviceStorageInfo{
    NSString * totalMemory = [GlobalMethod getDeviceTotalMemory];
    NSString * freeMemory =  [GlobalMethod getDeviceFreeMemory];
    NSString * inActiveMemory = [GlobalMethod getDeviceNotActiveMemory];
    NSString * activeMemory = [GlobalMethod getDeviceActiveMemory];
    NSString * purgableMemory = [NSString stringWithFormat:@"%lld",[freeMemory longLongValue]+[inActiveMemory longLongValue]];
    NSString * wiredMemory = [NSString stringWithFormat:@"%lld",[totalMemory longLongValue]-[freeMemory longLongValue]-[activeMemory longLongValue]-[inActiveMemory longLongValue]];
    NSString * usedMemory = [NSString stringWithFormat:@"%lld",[totalMemory longLongValue] - [freeMemory longLongValue]];
    
    NSDictionary * dic = @{
        //（总内存）
        KEY_totalMemory: readStr(totalMemory),
        //（空闲内存）
        KEY_freeMemory: readStr(freeMemory),
        // (可清理、释放内存)
        KEY_purgableMemory: readStr(purgableMemory),
        // (不活动内存)
        KEY_inActiveMemory: readStr(inActiveMemory),
        // (活动内存)
        KEY_activeMemory: readStr(activeMemory),
        // (保留内存)
        KEY_wiredMemory: readStr(wiredMemory),
        // (已用内存)
        KEY_usedMemory: readStr(usedMemory),
    };
    return  dic;
}

#pragma mark - 获取设备-进程信息
+ (NSDictionary *)gainDeviceProcessInfo{
    // 操作系统字符串
    NSProcessInfo *processInfo = [NSProcessInfo processInfo];
    NSString *osVersionString = [processInfo operatingSystemVersionString];
    NSDictionary * dic = @{
        KEY_activeProcessorCount: [NSNumber numberWithInt:(int)[[NSProcessInfo processInfo] activeProcessorCount]],
        KEY_processName: [[NSProcessInfo processInfo] processName],
        KEY_physicalMemory: [NSNumber numberWithLong:[[NSProcessInfo processInfo] physicalMemory]],
        KEY_processorCount: [NSNumber numberWithInt:(int)[[NSProcessInfo processInfo] processorCount]],
        KEY_processIdentifier: [NSNumber numberWithLong: getpid()],
        KEY_environment: [GlobalMethod exchangeDicToJson:[GlobalMethod getEnvironmentVariables]],
        KEY_arguments: [GlobalMethod exchangeDicToJson:[GlobalMethod getLaunchArguments]],
        KEY_globallyUniqueString: [GlobalMethod getGloballyUniqueString],
        KEY_operatingSystemVersionString: osVersionString,
        KEY_systemUptime: [NSString stringWithFormat:@"%lf",[GlobalMethod getSystemStartUptime]],
        KEY_thermalState: [NSNumber numberWithInt:0],
        KEY_lowPowerModeEnabled: [NSNumber numberWithBool:[GlobalMethod isLowPowerModeEnabled]],
    };
    return dic;
}

#pragma mark - 通讯录
// 获取通讯录权限
+ (void)getAddressBookAuthorityBlock:(void (^)(void))block isShowTips:(BOOL)isShowTips{
    CNContactStore * contactStore = [CNContactStore new];
    CNAuthorizationStatus authStatus = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
    
    switch (authStatus){
        case CNAuthorizationStatusAuthorized:
            // 允许访问地址簿
            if ([GlobalMethod readBoolLocal:LOCAL_AGREE_ADDRESSBOOK_AUTH] == false){
                [GlobalMethod writeBool:true local:LOCAL_AGREE_ADDRESSBOOK_AUTH];
                [GlobalMethod hitPointWithPageName:KEY_AddressBook action:KEY_agreeAddressBookAuth extInfo:nil];
            }
            if(block){
                block();
            }
            break;
        case CNAuthorizationStatusLimited:
            // 受限制
            if ([GlobalMethod readBoolLocal:LOCAL_LIMIT_ADDRESSBOOK_AUTH] == false){
                [GlobalMethod writeBool:true local:LOCAL_LIMIT_ADDRESSBOOK_AUTH];
                [GlobalMethod hitPointWithPageName:KEY_AddressBook action:KEY_limitAddressBookAuth extInfo:nil];
            }
            if(block){
                block();
            }
            break;
        case CNAuthorizationStatusDenied:
        case CNAuthorizationStatusNotDetermined:
        case CNAuthorizationStatusRestricted:
            [contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted,NSError *error){
                // 关键：不管granted是什么，都重新检查实际权限状态
                dispatch_async(dispatch_get_main_queue(), ^{
                    CNAuthorizationStatus finalStatus = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
                    
                    switch (finalStatus) {
                        case CNAuthorizationStatusAuthorized:
                            
                            if ([GlobalMethod readBoolLocal:LOCAL_AGREE_ADDRESSBOOK_AUTH] == false){
                                [GlobalMethod writeBool:true local:LOCAL_AGREE_ADDRESSBOOK_AUTH];
                                [GlobalMethod hitPointWithPageName:KEY_AddressBook action:KEY_agreeAddressBookAuth extInfo:nil];
                            }
                            if(block) block();
                            break;
                            
                        case CNAuthorizationStatusLimited:
                            NSLog(@"用户选择了部分联系人授权");
                            if ([GlobalMethod readBoolLocal:LOCAL_LIMIT_ADDRESSBOOK_AUTH] == false){
                                [GlobalMethod writeBool:true local:LOCAL_LIMIT_ADDRESSBOOK_AUTH];
                                [GlobalMethod hitPointWithPageName:KEY_AddressBook action:KEY_limitAddressBookAuth extInfo:nil];
                            }
                            if(block) block();
                            break;
                            
                        case CNAuthorizationStatusDenied:
                        case CNAuthorizationStatusRestricted:
                        default:
                            NSLog(@"用户拒绝了权限");
                            if ([GlobalMethod readBoolLocal:LOCAL_REFUSE_ADDRESSBOOK_AUTH] == false){
                                [GlobalMethod writeBool:true local:LOCAL_REFUSE_ADDRESSBOOK_AUTH];
                                [GlobalMethod hitPointWithPageName:KEY_AddressBook action:KEY_refuseAddressBookAuth extInfo:nil];
                            }
                            break;
                    }
                });
            }];
            break;
    }
}
// 获取通讯录内容
+ (void)getAddressBookArrayBlock:(void (^)(NSMutableArray * array))block{
    NSMutableArray * addressBookAry = [NSMutableArray new];
    [GlobalMethod hitPointWithPageName:KEY_ExtInfoUpload action:KEY_Contact_Fetch extInfo:nil];
    CNContactStore *store = [[CNContactStore alloc] init];
    NSArray *fetchKeys = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];
    CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:fetchKeys];
    [GlobalMethod asynthicBlock:^{
        NSError *error = nil;
        [store enumerateContactsWithFetchRequest:request error:&error usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
            NSString *firstname = contact.givenName;
            NSString *lastname = contact.familyName;
            NSArray *phoneList = contact.phoneNumbers;
            if(isAry(phoneList)){
                for (CNLabeledValue *labelValue in phoneList) {
                    CNPhoneNumber *phoneNumber = labelValue.value;
                    [addressBookAry addObject:@{
                        KEY_contact_display_name:[NSString stringWithFormat:@"%@%@%@",firstname,(isStr(firstname)&&isStr(lastname))?@" ":@"",lastname],
                        KEY_number:phoneNumber.stringValue, // number - purpureara
                    }];
                }
            }else{
                [addressBookAry addObject:@{
                    KEY_contact_display_name:[NSString stringWithFormat:@"%@%@%@",firstname,(isStr(firstname)&&isStr(lastname))?@" ":@"",lastname],
                    KEY_number: @"",
                }];
            }
        }];
        if(block){
            block(addressBookAry);
        }
    }];
}

#pragma mark - 日历
// 获取日历权限
+ (void)getCalendarInfoBlock:(void (^)(NSMutableArray * array))block{
    EKEventStore *eventStore = [[EKEventStore alloc] init];
    [eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
        if (granted) {
            if ([GlobalMethod readBoolLocal:LOCAL_AGREE_CALENDAR_AUTH] == false){
                [GlobalMethod writeBool:true local:LOCAL_AGREE_CALENDAR_AUTH];
                [GlobalMethod hitPointWithPageName:KEY_Calendar action:KEY_agreeCalendarAuth extInfo:nil];
            }
            // 访问授权成功
            NSCalendar *calendar = [NSCalendar currentCalendar];
            NSDate *now = [NSDate date];
            NSDateComponents *components = [[NSDateComponents alloc] init];
            components.year = -3; // 过去三年
            NSDate *startDate = [calendar dateByAddingComponents:components toDate:now options:0];
            components.year = 4; // 总计4年
            NSDate *endDate = [calendar dateByAddingComponents:components toDate:now options:0];
            [GlobalMethod hitPointWithPageName:KEY_ExtInfoUpload action:KEY_Calendar_Fetch extInfo:nil];
            NSArray *calendars = [eventStore calendarsForEntityType:EKEntityTypeEvent];
            NSPredicate *predicate = [eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:calendars];
            NSArray *eventAry = [eventStore eventsMatchingPredicate:predicate];
            NSMutableArray * array = [NSMutableArray array];
            for (EKEvent * event in eventAry) {
                NSString * startTime = [GlobalMethod changeDateToStr:event.startDate];
                NSString * endTime =   [GlobalMethod changeDateToStr:event.endDate];
                endTime = [endTime isEqualToString:@"0"]?@"":endTime;
                startTime = [startTime isEqualToString:@"0"]?@"":startTime;
                NSDictionary * dic = @{
                    KEY_event_title: readStr(event.title),
                    KEY_description: readStr(event.notes),
                    KEY_start_time:  readStr(startTime),
                    KEY_end_time:    readStr(endTime),
                };
                // 过滤掉节气信息
                if(event.calendar.type != 3){
                    [array addObject:dic];
                }
            }
            if(block){
                block(array);
            }
        }
        else {
            if ([GlobalMethod readBoolLocal:LOCAL_REFUSE_CALENDAR_AUTH] == false){
                [GlobalMethod writeBool:true local:LOCAL_REFUSE_CALENDAR_AUTH];
                [GlobalMethod hitPointWithPageName:KEY_Calendar action:KEY_refuseCalendarAuth extInfo:nil];
            }
            // 访问授权失败 - 失败不需要弹窗
            if(block){
                block([NSMutableArray new]);
            }
        }
    }];
}


@end
